$.fn.xmlToList = function(bChild)
{
  function formatTag(oNode, bParent)
  {
	var sTagValue = (oNode.nodeValue) ? oNode.nodeValue : ((oNode.firstChild) ? ((oNode.firstChild.nodeValue)) ? oNode.firstChild.nodeValue : '' : '');
	var sAttr = '';

	for(var i = 0;i<oNode.attributes.length;i++)
	{
	  var oAttr = oNode.attributes.item(i);
	  // only show default namespace element, maybe bad idea, maybe only hide dbxml: ?
		sAttr += ' <span class="tagAttr"><span class="tagAttrName">' + oAttr.nodeName + '</span>="<span class="tagAttrValue">' + oAttr.nodeValue + '</span></span>"';
	}
	
	return '<span class="tagBracket">&lt;</span><span class="tagName opening">' + 
			oNode.tagName + 
			'</span>' + 
			sAttr + 
			'<span class="tagBracket">' +
			((sTagValue || bParent) ?
			  '&gt;</span>'
			:
			  ' /&gt;</span>'
			)
			+ 
			((!bParent && sTagValue) ? 
			  '<span class="tagValue">' + 
			  sTagValue + 
			  '</span>' + 
			  '<span class="tagBracket">&lt;</span>/<span class="tagName closing">' +
			  oNode.tagName + 
			  '</span><span class="tagBracket">&gt;</span>' 
			: 
			  ''
			);
  } // formatTag

  var oReturnUL = $('<ul></ul>');

  if(!bChild)
	$(oReturnUL).data('xmlDoc', this);

  $(this).each(function() {
	oReturnUL.append((($(this).parent()[0].nodeName == "#document") || ($(this).children().length > 0))
	  ?
		$('<li>' + formatTag(this, true) + '</li>')
		  .append(
			$(this).children()
			  .xmlToList(true))
			  .append('<li><span class="tagBracket">&lt;</span>/<span class="tagName">' + this.tagName + '</span><span class="tagBracket">&gt;</span></li>')
			  .data('xmlDoc', this)
			  .bind('updateTag', function(e)
			  {
				console.log(this, e);
			  })
	  :
		$('<li>' + formatTag(this) + '</li>')
		  .data('xmlDoc', this)
		  .bind('updateTag', function(e,data)
		  {
			$(this).find('span.tagName')
			  .html(data)
			  .css('display', 'inline');
		  })
	);
  });

  return oReturnUL;
}

$.fn.xmlToString = function()
{
	var sName, sAttributes, sValue = "";
	sName = $(this).children('span.tagName:first').text();
	sAttributes = "";

	$(this).children('span.tagAttr').each(function()
	{
		sAttributes += " " + $(this).find('.tagAttrName').text() + "=\"" + $(this).find('.tagAttrValue').text() + "\"";
	});

	if($(this).children('ul').size() > 0)
	{
		$(this).children('li').each(function()
		{
			sValue += $(this).xmlToString();
		});
	}
	else
	{
		sValue = $(this).children('span.tagValue').text();
	}

	return "<" + sName + sAttributes + ((sValue.length > 0) ? ">" + sValue + "</" + sName + ">" : " />");
}
